package com.zhs.study.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.*;

/**
 * 线程池工具
 * @author zhenghuisheng
 * @date : 2023/3/22
 */
public class ThreadPoolUtil {
    //日志级别(由高到低)：fatal -> error -> warn -> info -> debug,低级别的会输出高级别的信息，高级别的不会输出低级别的信息
    private static final Logger log = LoggerFactory.getLogger(ThreadPoolUtil.class);
    //构建线程池
    public static ThreadPoolExecutor pool = null;

    //向线程池中添提交任务,无参数返回
    //判断核心线程数数量，阻塞队列，创建非核心线程数，拒绝策略
    public static void execute(Runnable runnable) {
        getThreadPool().execute(runnable);
    }

    //向线程池中添提交任务,将任务返回
    //判断核心线程数数量，阻塞队列，创建非核心线程数，拒绝策略
    public static <T> Future<?> submit(Runnable runnable) {
        //提交任务，并将任务返回
        Future<?> future = getThreadPool().submit(runnable);
        //将任务存储在hash表中
        return future;
    }

    /**
     * io密集型：最大核心线程数为2N,可以给cpu更好的轮换，
     *           核心线程数不超过2N即可，可以适当留点空间
     * cpu密集型：最大核心线程数为N或者N+1，N可以充分利用cpu资源，N加1是为了防止缺页造成cpu空闲，
     *           核心线程数不超过N+1即可
     * 使用线程池的时机：1,单个任务处理时间比较短 2,需要处理的任务数量很大
     * 参考：https://blog.csdn.net/yuyan_jia/article/details/120298564
     */

    public static synchronized ThreadPoolExecutor getThreadPool() {
        if (pool == null) {
            //获取当前机器的cpu
            int cpuNum = Runtime.getRuntime().availableProcessors();
            log.info("当前机器的cpu的个数为：" + cpuNum);
            int maximumPoolSize = cpuNum * 2 ;
            pool = new ThreadPoolExecutor(
                    maximumPoolSize - 2,
                    maximumPoolSize,
                    5L,   //5s
                    TimeUnit.SECONDS,
                    new PriorityBlockingQueue<>(),  //数组有界队列
                    Executors.defaultThreadFactory(), //默认的线程工厂
                    new ThreadPoolExecutor.AbortPolicy());  //直接抛异常，默认异常
        }

        return pool;
    }

}
